package com.ziven.common.widget.window;

import android.content.Context;
import android.content.DialogInterface;
import android.graphics.drawable.Drawable;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.Space;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;

import com.ziven.common.widget.value.NullValue;
import com.ziven.common.widget.value.TakeEffect;
import com.ziven.easygo.util.Standard;
import com.ziven.easygo.util.ViewUtils;

/**
 * @author Ziven
 */
public class CommonDialog implements Standard {

    private final AlertDialog.Builder builder;
    private AlertDialog alertDialog;
    private int gravity = Gravity.BOTTOM;
    private boolean centerButton = true;
    private boolean canceledOnTouchOutside = true;
    private boolean removeLeftRightPadding = false;

    public CommonDialog(@NonNull Context context, int themeResId) {
        builder = new AlertDialog.Builder(context, themeResId);
    }

    public AlertDialog.Builder builder() {
        return builder;
    }

    public CommonDialog setTitle(int titleId) {
        builder().setTitle(titleId);
        return this;
    }

    public CommonDialog setTitle(String title) {
        builder().setTitle(title);
        return this;
    }

    public CommonDialog setMessage(int messageId) {
        builder().setMessage(messageId);
        return this;
    }

    public CommonDialog setMessage(String message) {
        builder().setMessage(message);
        return this;
    }

    public CommonDialog setPositiveButton(int titleId, DialogInterface.OnClickListener listener) {
        builder().setPositiveButton(titleId, listener);
        return this;
    }

    public CommonDialog setPositiveButton(String title, DialogInterface.OnClickListener listener) {
        builder().setPositiveButton(title, listener);
        return this;
    }

    public CommonDialog setPositiveButtonIcon(Drawable icon) {
        builder().setPositiveButtonIcon(icon);
        return this;
    }

    public CommonDialog setNegativeButton(int titleId, DialogInterface.OnClickListener listener) {
        builder().setNegativeButton(titleId, listener);
        return this;
    }

    public CommonDialog setNegativeButton(String title, DialogInterface.OnClickListener listener) {
        builder().setNegativeButton(title, listener);
        return this;
    }

    public CommonDialog setNegativeButtonIcon(Drawable icon) {
        builder().setNegativeButtonIcon(icon);
        return this;
    }

    public CommonDialog setNeutralButton(int titleId, DialogInterface.OnClickListener listener) {
        builder().setNeutralButton(titleId, listener);
        return this;
    }

    public CommonDialog setNeutralButton(String title, DialogInterface.OnClickListener listener) {
        builder().setNeutralButton(title, listener);
        return this;
    }

    public CommonDialog setNeutralButtonIcon(Drawable icon) {
        builder().setNeutralButtonIcon(icon);
        return this;
    }

    public CommonDialog setGravity(int gravity) {
        this.gravity = gravity;
        return this;
    }

    public CommonDialog centerButton(boolean center) {
        centerButton = center;
        return this;
    }

    public CommonDialog setCanceledOnTouchOutside(boolean canceledOnTouchOutside) {
        this.canceledOnTouchOutside = canceledOnTouchOutside;
        return this;
    }

    public CommonDialog setRemoveLeftRightPadding(boolean removeLeftRightPadding) {
        this.removeLeftRightPadding = removeLeftRightPadding;
        return this;
    }

    public boolean isShowing() {
        return alertDialog != null && alertDialog.isShowing();
    }

    public void show() {
        show(TakeEffect.values(NullValue.VALUE));
    }

    public void show(@NonNull TakeEffect effect) {
        if(alertDialog == null) {
            alertDialog = builder().show();
            alertDialog.setCanceledOnTouchOutside(canceledOnTouchOutside);
            Window window = window();
            if(window != null) {
                takeEffect(window, effect);
            }
        } else {
            alertDialog.show();
        }
    }

    public void dismiss() {
        if(alertDialog != null) {
            alertDialog.dismiss();
        }
    }

    @Nullable
    private Window window() {
        return alertDialog != null ? alertDialog.getWindow() : null;
    }

    private void takeEffect(@NonNull Window window,
                            @NonNull TakeEffect effect) {
        window.setGravity(gravity);
        if(removeLeftRightPadding) {
            window.setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.WRAP_CONTENT);
        }
        if(centerButton) {
            Button positive = window.findViewById(android.R.id.button1);
            Button negative = window.findViewById(android.R.id.button2);
            Button neutral = window.findViewById(android.R.id.button3);
            if(positive != null && negative != null && neutral != null) {
                removeSpace(positive.getParent());
                centerButton(neutral);
                centerButton(negative);
                centerButton(positive);
            }
        }
        effect.takeEffect(window.getDecorView());
    }

    private void removeSpace(ViewParent vp) {
        if(vp instanceof LinearLayout) {
            ViewUtils.forEachChild((LinearLayout) vp, child -> {
                if(child instanceof Space) {
                    child.setVisibility(View.GONE);
                }
            });
        }
    }

    private void centerButton(@NonNull Button button) {
        ViewGroup.LayoutParams params = button.getLayoutParams();
        if(params instanceof LinearLayout.LayoutParams) {
            ((LinearLayout.LayoutParams) params).gravity = Gravity.CENTER_HORIZONTAL;
            ((LinearLayout.LayoutParams) params).weight = 0.5f;
            button.setLayoutParams(params);
        }
    }

    public static TakeEffect title() {
        return TakeEffect.values().accept(my -> my.viewId =  androidx.appcompat.R.id.alertTitle);
    }

    public static TakeEffect message() {
        return TakeEffect.values().accept(my -> my.viewId =  android.R.id.message);
    }

    public static TakeEffect positive() {
        return TakeEffect.values(NullValue.VALUE).accept(my -> my.viewId =  android.R.id.button1);
    }

    public static TakeEffect negative() {
        return TakeEffect.values().accept(my -> my.viewId =  android.R.id.button2);
    }

    public static TakeEffect neutral() {
        return TakeEffect.values().accept(my -> my.viewId =  android.R.id.button3);
    }
}
